﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace ConsoleLibraryTestApp
{
    public partial class Form1 : Form
    {
        NetworkStream ns = null;
        TcpClient server;
        Thread rcvThread = null;
        bool terminalConnected = false;
        string stringData = "";  


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ansiConsole1.LocalEcho = true;
            ansiConsole1.Focus();
            ansiConsole1.TextChanged += new ConsoleLib.TextChangedEventHandler(ansiConsole1_TextChanged);
            ansiConsole1.AnsiCursorLocationRequest += new ConsoleLib.AnsiCursorLocationRequestEventHandler(ansiConsole1_AnsiCursorLocationRequest);
            ansiConsole1.AnsiQueryDeviceStatusRequest +=new ConsoleLib.AnsiQueryDeviceStatusEventRequestHandler(ansiConsole1_AnsiQueryDeviceStatusRequest);

            ansiConsole1.CursorMode = true;

            ansiConsole1.WriteLine("Hello World!");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            terminal_connect();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //test_ansicolors();
            string x = textBox3.Text.Replace("~", "\x1b[");
            ansiConsole1.Write(x);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            test_readline();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            test_screen();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            string file = textBox4.Text;

            ansiConsole1.ReadFile(file);
        }

        private void button6_Click(object sender, EventArgs e)
        {
            terminal_disconnect();
        }

        private void terminal_connect()
        {
            try
            {
                server = new TcpClient(textBox5.Text, 23);
                button1.Enabled = false;
                button6.Enabled = true;
            }
            catch (SocketException)
            {
                ansiConsole1.Write("Unable to connect to server");
                button1.Enabled = true;
                button6.Enabled = false;
                return;
            }

            NetworkStream ns = server.GetStream();
            ansiConsole1.Focus();
            ansiConsole1.LocalEcho = false;
            terminalConnected = true;

            Thread rcvThread = new Thread(new ParameterizedThreadStart(terminal_NonBlockReceive));
            rcvThread.Start(ns);
            
            while (true)
            {
                if (stringData.Length > 0)
                {
                    ansiConsole1.Write(stringData);
                    stringData = "";
                }

                Application.DoEvents();
            }
        }

        private void terminal_NonBlockReceive(object netStream)
        {
            NetworkStream ns = (NetworkStream)netStream;

            while (terminalConnected)
            {
                if (ns.DataAvailable)
                {
                    byte[] data = new byte[20000];
                    int recv = ns.Read(data, 0, data.Length);
                    stringData = Encoding.GetEncoding(1252).GetString(data, 0, recv);
                }
            }
        }

        private void terminal_disconnect()
        {
            terminalConnected = false;
            
            try
            {   
                ns = server.GetStream();
                ns.Close();
                server.Close();
                rcvThread.Abort();
                
            }
            catch (Exception ex)
            {
            }

            button1.Enabled = true;
            button6.Enabled = false;
        }

        private void test_ansicolors()
        {
            string s = "{ESC}[7h{ESC}[0;40;37m{ESC}[?33hThis is a test°";
            s = s.Replace("{ESC}", "\x1b");
            ansiConsole1.Write(s);

            ansiConsole1.Write("\x1b[31mSo is this.");
            ansiConsole1.Write("\x1b[1;32mAnd this");
            ansiConsole1.Write("\x1b[20;20H\x1b[3A\x1b[3D\x1b[6n");
        }

        private void test_screen()
        {
            string s = "";

            s = "{ESC}[40m{ESC}[2J{ESC}[0;33m²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²{ESC}[s";
            s = s.Replace("{ESC}", "\x1b");
            ansiConsole1.Write(s);

            s = "{ESC}[u²²²²²²²²²²²²²²²²²²² °°°{ESC}[1;37mÛÛ{ESC}[0;33m°°°°°°°°°°°°°°°°°°°°{ESC}[1;37mÛÛ{ESC}[s";
            s = s.Replace("{ESC}", "\x1b");
            ansiConsole1.Write(s);

            s = "{ESC}[u{ESC}[0;33m°°°°°°°°°°°°°°°°°°°°°°°°{ESC}[1;37mÛÛ{ESC}[0;33m°°°°°°°°°°°°°°°°°°°°{ESC}[1;37m{ESC}[s";
            s = s.Replace("{ESC}", "\x1b");

            s = @"[1;37;44m[2J
                                   ÜÜÜÜÜÜÜÜÜÜÜÜ
                          ÜÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜÜ
                      ÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜ
                    ÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜ
                   ÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜ
                  ÞÛ[40mÛÛÛð ßßß[37mÛÛÛÛÛ[s
[uÛÛÛ[0;30;43m ú [1;37;40mÛÛÛÛÛÛÛÛÛÛßßß ðÛ[44mÛÛÛÛÛÝ
[18CÛÛ[40mÛÛÛÝ  [33mÜÛÜ  [37mßÛ[s
[uÛÛ[0;30;43m     [1;37;40mÛÛÛÛßß[33mÜÛÜ  [37m  ÞÛ[44mÛÛÛÛÛÛ
[18CÛÛ[40mÛÛÛÛ [33mÞÛ ÛÝ  [37mÛ[s
[uÛ[0;30;43m þú þ  [1;37;40mÛÛÛ [33mÞÛ ÛÝ  [37mÞÛÛ[44mÛÛÛÛÛÛ
[17CÞÛÛ[40mÛÛÛÛÛÜ[33mßÛß  [37mÜÛ[s
[u[0;30;43m  ú      [1;37;40mÛÛÜ [33mßÛß  [37mÜÛÛÛ[44mÛÛÛÛÛÛÝ
[17CÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[30;43m            [37;44mÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
                ÞÛÛÛÛÛÛÛÛÛÛÛÛÛ[0;30;43mÄÄ   ú     Ä[s
[uÄÄÄÄ[1;37;44mÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
[16CÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[37;43m      Ü[44mÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÝ
                ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[0;30;43m ú  [1;37;44mÛÛÛÛÛÛÛ[s
[uÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
                ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[30;43mú [37;44mÛÛÛÛÛÛÛÛÛÛÛÛ[s
[uÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[0;34;40m
ÛÛÛÛÛÛÛÛÛÛÛÛßßß [1;37;44mÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[s
[uÛÛÛÛÛÛÛÛÝ[0;34;40m
ÛÛÛÛÛÛÛßßß     [1;37;40mÞÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[44mÛÛÛÛÛÛ[s
[uÛÛÛÛÛÛÛÛÛÛÛÛÛÝ[0;34;40m
ÛÛÛßß          [1;37;44mÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[s
[uÛÛÛÛÛÛÛÛÛ[0;34m
ß              [1;37;40mÛÛÛÛÛÛÛÛÛ°ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛß ÛÛÛÛÛÛß²ÛÛÛ[s
[uÛÛÛÛÛÛÛÛÛ[0;34m
                [1;37;40mÛß°ßÛÛÛ  °ÛÛÛÛ²±ÛÛÛÛÛÛßßÛ²  ÞÛÛß    ²ÛÛ[s
[uÛß²Û±Û ßÛ[37;44mÝ[0;34;40m
                [1;37;40mß    ß    °ÛÛ±  ßÛ²ß    ß    ß      °²Û[s
[uÝ  ß     ß[0;34m
                [1;37;40m           ±²                         ß[s
[u          [0;30;44mÝ[34;40m
                                                                 [s
[u[0;30;44mÝ[34;40m
                                                                 [2A
[0m";


            ansiConsole1.Write(s);

        }

        private void test_readline()
        {
            ansiConsole1.Write("Please type something:");
            string x = ansiConsole1.ReadLine();

            textBox2.Text = x;
        }

        private void ansiConsole1_TextChanged(object sender, EventArgs e)
        {
            textBox1.Text = "Row: " + ansiConsole1.Row + " - Col: " + ansiConsole1.Col + Environment.NewLine + "Pos: " + ansiConsole1.CurrentBufferLocation;
        }

        private void ansiConsole1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (terminalConnected)
            {
                ns = server.GetStream();

                if (ns.CanWrite)
                {
                    string s = Convert.ToString(e.KeyChar);
                    byte[] b = Encoding.GetEncoding(1252).GetBytes(s);

                    try
                    {
                        ns.Write(b, 0, b.Length);
                    }
                    catch (Exception ex)
                    {
                        ansiConsole1.Write("Socket closed.");
                        terminal_disconnect();
                    }
                }
            }
        }

        private void ansiConsole1_AnsiCursorLocationRequest(object sender, EventArgs e)
        {
            int r = ansiConsole1.Row;
            int c = ansiConsole1.Col;

            string x = "\x1b[" + Convert.ToString(r) + ";" + Convert.ToString(c) + "R";

            System.Diagnostics.Debug.WriteLine("Sending " + x);

            byte[] bytes = System.Text.Encoding.GetEncoding(1252).GetBytes(x);

            ns.Write(bytes, 0, bytes.Length);
        }

        private void ansiConsole1_AnsiQueryDeviceStatusRequest(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Sending ESC[0n (OK)");

            string x = "\x1b[0n";
            byte[] bytes = System.Text.Encoding.GetEncoding(1252).GetBytes(x);
            ns.Write(bytes, 0, bytes.Length);
        }





    }
}
